/**
 * ECS 命令队列系统
 * 
 * 职责：
 * 1. 在逻辑系统和渲染系统之间传递命令
 * 2. 解耦逻辑层和渲染层
 * 3. 支持命令优先级和批处理
 * 4. 支持命令依赖和拓扑排序
 * 5. 提供命令撤销/重做功能（可选）
 * 
 * 使用场景：
 * - 逻辑系统：发送渲染命令（播放动画、移动节点等）
 * - 渲染系统：执行命令并更新视图
 * 
 * @author AI Assistant
 * @date 2025-11-26
 */

import { ecs } from "../../../core/ecs/ECS";
import { ViewComponent } from "../component/ViewComponent";
import { Vec3, Color } from "cc";
import { CommandDependencyManager } from "./CommandDependency";
import { Log } from "../../../core/logger/LoggerGlobal";

/**
 * 命令类型枚举
 */
export enum CommandType {
    // 节点操作
    SET_POSITION = 'set_position',
    SET_ROTATION = 'set_rotation',
    SET_SCALE = 'set_scale',
    SET_VISIBLE = 'set_visible',
    SET_ACTIVE = 'set_active',
    
    // 动画操作
    PLAY_ANIMATION = 'play_animation',
    STOP_ANIMATION = 'stop_animation',
    PAUSE_ANIMATION = 'pause_animation',
    
    // Sprite 操作
    SET_SPRITE_FRAME = 'set_sprite_frame',
    SET_SPRITE_COLOR = 'set_sprite_color',
    SET_SPRITE_OPACITY = 'set_sprite_opacity',
    
    // Label 操作
    SET_LABEL_TEXT = 'set_label_text',
    SET_LABEL_COLOR = 'set_label_color',
    
    // 特效操作
    PLAY_EFFECT = 'play_effect',
    PLAY_SOUND = 'play_sound',
    
    // 节点生命周期
    CREATE_NODE = 'create_node',
    DESTROY_NODE = 'destroy_node',
    
    // 自定义命令
    CUSTOM = 'custom'
}

/**
 * 命令优先级
 */
export enum CommandPriority {
    LOW = 0,
    NORMAL = 1,
    HIGH = 2,
    CRITICAL = 3
}

/**
 * 命令接口
 */
export interface ICommand {
    /** 命令 ID（自动生成） */
    id: string;
    
    /** 命令类型 */
    type: CommandType;
    
    /** 目标实体 ID */
    entityId: number;
    
    /** 命令参数 */
    params: any;
    
    /** 优先级 */
    priority: CommandPriority;
    
    /** 创建时间 */
    timestamp: number;
    
    /** 是否已执行 */
    executed: boolean;
    
    /** 依赖的命令 ID 列表（可选） */
    dependencies?: string[];
    
    /** 执行回调（可选） */
    onExecute?: (result: any) => void;
    
    /** 错误回调（可选） */
    onError?: (error: Error) => void;
}

/**
 * 命令执行器接口
 */
export interface ICommandExecutor {
    /**
     * 执行命令
     * @param command 命令对象
     * @returns 执行结果
     */
    execute(command: ICommand): any;
    
    /**
     * 检查是否可以执行该类型的命令
     * @param commandType 命令类型
     */
    canExecute(commandType: CommandType): boolean;
}

/**
 * 命令队列类（使用依赖注入）
 */
export class CommandQueue {
    // 命令队列（按优先级分组）
    private queues: Map<CommandPriority, ICommand[]> = new Map();
    
    // 命令执行器映射
    private executors: Map<CommandType, ICommandExecutor> = new Map();
    
    // 已执行命令历史（用于撤销/重做）
    private history: ICommand[] = [];
    
    // 命令 ID 计数器
    private commandIdCounter: number = 0;
    
    // 是否启用历史记录
    private enableHistory: boolean = false;
    
    // 最大历史记录数
    private maxHistorySize: number = 100;
    
    // 依赖管理器
    private dependencyManager: CommandDependencyManager = new CommandDependencyManager();
    
    // 是否启用依赖排序
    private enableDependencySort: boolean = false;
    
    // 统计信息
    private stats = {
        totalCommands: 0,
        executedCommands: 0,
        failedCommands: 0,
        averageExecutionTime: 0,
        dependencySorts: 0
    };
    
    constructor() {
        this.initializeQueues();
        Log.ecs.debug('CommandQueue 已创建（DI）');
    }
    
    /**
     * 初始化队列
     */
    private initializeQueues(): void {
        this.queues.set(CommandPriority.LOW, []);
        this.queues.set(CommandPriority.NORMAL, []);
        this.queues.set(CommandPriority.HIGH, []);
        this.queues.set(CommandPriority.CRITICAL, []);
    }
    
    /**
     * 注册命令执行器
     * @param commandType 命令类型
     * @param executor 执行器
     */
    registerExecutor(commandType: CommandType, executor: ICommandExecutor): void {
        this.executors.set(commandType, executor);
        Log.ecs.debug('注册命令执行器', { commandType });
    }
    
    /**
     * 添加命令到队列
     * @param commandType 命令类型
     * @param entityId 目标实体 ID
     * @param params 命令参数
     * @param priority 优先级（默认 NORMAL）
     * @param callbacks 回调函数
     * @param dependencies 依赖的命令 ID 列表（可选）
     * @returns 命令 ID
     */
    addCommand(
        commandType: CommandType,
        entityId: number,
        params: any,
        priority: CommandPriority = CommandPriority.NORMAL,
        callbacks?: {
            onExecute?: (result: any) => void;
            onError?: (error: Error) => void;
        },
        dependencies?: string[]
    ): string {
        const command: ICommand = {
            id: this.generateCommandId(),
            type: commandType,
            entityId,
            params,
            priority,
            timestamp: Date.now(),
            executed: false,
            dependencies: dependencies,
            onExecute: callbacks?.onExecute,
            onError: callbacks?.onError
        };
        
        // 添加到对应优先级的队列
        const queue = this.queues.get(priority);
        if (queue) {
            queue.push(command);
            this.stats.totalCommands++;
        }
        
        // 如果启用依赖排序，添加到依赖管理器
        if (this.enableDependencySort && dependencies && dependencies.length > 0) {
            this.dependencyManager.addCommand(command, dependencies);
        }
        
        return command.id;
    }
    
    /**
     * 批量添加命令
     * @param commands 命令数组
     */
    addCommands(commands: Array<{
        type: CommandType;
        entityId: number;
        params: any;
        priority?: CommandPriority;
    }>): string[] {
        const commandIds: string[] = [];
        
        for (const cmd of commands) {
            const id = this.addCommand(
                cmd.type,
                cmd.entityId,
                cmd.params,
                cmd.priority || CommandPriority.NORMAL
            );
            commandIds.push(id);
        }
        
        return commandIds;
    }
    
    /**
     * 执行队列中的所有命令
     * @param maxExecutionTime 最大执行时间（毫秒），超时则停止执行
     */
    executeAll(maxExecutionTime: number = 16): void {
        const startTime = performance.now();
        let executedCount = 0;
        
        // 如果启用依赖排序，使用拓扑排序
        if (this.enableDependencySort) {
            executedCount = this.executeWithDependencies(startTime, maxExecutionTime);
        } else {
            executedCount = this.executeByPriority(startTime, maxExecutionTime);
        }
        
        if (executedCount > 0) {
            const executionTime = performance.now() - startTime;
            this.updateStats(executionTime, executedCount);
        }
        
        // 清空依赖管理器
        if (this.enableDependencySort) {
            this.dependencyManager.clear();
        }
    }
    
    /**
     * 按优先级执行命令（原有逻辑）
     */
    private executeByPriority(startTime: number, maxExecutionTime: number): number {
        let executedCount = 0;
        
        // 按优先级从高到低执行
        const priorities = [
            CommandPriority.CRITICAL,
            CommandPriority.HIGH,
            CommandPriority.NORMAL,
            CommandPriority.LOW
        ];
        
        for (const priority of priorities) {
            const queue = this.queues.get(priority);
            if (!queue || queue.length === 0) continue;
            
            // 执行该优先级的命令
            while (queue.length > 0) {
                // 检查是否超时
                if (performance.now() - startTime > maxExecutionTime) {
                    Log.ecs.warn('命令执行超时', {
                        remaining: this.getTotalCommandCount()
                    });
                    return executedCount;
                }
                
                const command = queue.shift()!;
                this.executeCommand(command);
                executedCount++;
            }
        }
        
        return executedCount;
    }
    
    /**
     * 使用依赖排序执行命令
     */
    private executeWithDependencies(startTime: number, maxExecutionTime: number): number {
        let executedCount = 0;
        
        // 收集所有待执行的命令
        const allCommands: ICommand[] = [];
        for (const queue of this.queues.values()) {
            allCommands.push(...queue);
        }
        
        if (allCommands.length === 0) {
            return 0;
        }
        
        // 将所有命令添加到依赖管理器
        for (const command of allCommands) {
            if (command.dependencies && command.dependencies.length > 0) {
                this.dependencyManager.addCommand(command, command.dependencies);
            } else {
                // 没有依赖的命令也要添加
                this.dependencyManager.addCommand(command, []);
            }
        }
        
        // 拓扑排序
        const sortedCommands = this.dependencyManager.topologicalSort();
        
        if (!sortedCommands) {
            // 有循环依赖，回退到按优先级执行
            Log.ecs.error('检测到循环依赖，回退到按优先级执行');
            this.dependencyManager.clear();
            return this.executeByPriority(startTime, maxExecutionTime);
        }
        
        this.stats.dependencySorts++;
        
        // 清空原有队列
        for (const queue of this.queues.values()) {
            queue.length = 0;
        }
        
        // 按排序后的顺序执行
        for (const command of sortedCommands) {
            // 检查是否超时
            if (performance.now() - startTime > maxExecutionTime) {
                Log.ecs.warn('命令执行超时', {
                    executed: executedCount,
                    total: sortedCommands.length
                });
                
                // 将未执行的命令放回队列
                for (let i = executedCount; i < sortedCommands.length; i++) {
                    const remainingCmd = sortedCommands[i];
                    const queue = this.queues.get(remainingCmd.priority);
                    if (queue) {
                        queue.push(remainingCmd);
                    }
                }
                
                return executedCount;
            }
            
            this.executeCommand(command);
            executedCount++;
        }
        
        return executedCount;
    }
    
    /**
     * 执行单个命令
     * @param command 命令对象
     */
    private executeCommand(command: ICommand): void {
        const executor = this.executors.get(command.type);
        
        if (!executor) {
            Log.ecs.warn('未找到命令执行器', { commandType: command.type });
            this.stats.failedCommands++;
            
            if (command.onError) {
                command.onError(new Error(`未找到执行器: ${command.type}`));
            }
            return;
        }
        
        try {
            const result = executor.execute(command);
            command.executed = true;
            this.stats.executedCommands++;
            
            // 添加到历史记录
            if (this.enableHistory) {
                this.addToHistory(command);
            }
            
            // 执行回调
            if (command.onExecute) {
                command.onExecute(result);
            }
        } catch (error) {
            Log.ecs.error('命令执行失败', {
                commandType: command.type,
                entityId: command.entityId,
                error
            });
            this.stats.failedCommands++;
            
            if (command.onError) {
                command.onError(error as Error);
            }
        }
    }
    
    /**
     * 添加到历史记录
     */
    private addToHistory(command: ICommand): void {
        this.history.push(command);
        
        // 限制历史记录大小
        if (this.history.length > this.maxHistorySize) {
            this.history.shift();
        }
    }
    
    /**
     * 生成命令 ID
     */
    private generateCommandId(): string {
        return `cmd_${++this.commandIdCounter}_${Date.now()}`;
    }
    
    /**
     * 更新统计信息
     */
    private updateStats(executionTime: number, executedCount: number): void {
        const avgTime = this.stats.averageExecutionTime;
        const totalExecuted = this.stats.executedCommands;
        
        this.stats.averageExecutionTime = 
            (avgTime * (totalExecuted - executedCount) + executionTime) / totalExecuted;
    }
    
    /**
     * 获取队列中的命令总数
     */
    getTotalCommandCount(): number {
        let count = 0;
        for (const queue of this.queues.values()) {
            count += queue.length;
        }
        return count;
    }
    
    /**
     * 获取指定优先级的命令数量
     */
    getCommandCount(priority: CommandPriority): number {
        const queue = this.queues.get(priority);
        return queue ? queue.length : 0;
    }
    
    /**
     * 清空所有队列
     */
    clear(): void {
        for (const queue of this.queues.values()) {
            queue.length = 0;
        }
        Log.ecs.info('命令队列已清空');
    }
    
    /**
     * 清空指定优先级的队列
     */
    clearPriority(priority: CommandPriority): void {
        const queue = this.queues.get(priority);
        if (queue) {
            queue.length = 0;
        }
    }
    
    /**
     * 启用历史记录
     */
    enableHistoryTracking(maxSize: number = 100): void {
        this.enableHistory = true;
        this.maxHistorySize = maxSize;
    }
    
    /**
     * 禁用历史记录
     */
    disableHistoryTracking(): void {
        this.enableHistory = false;
        this.history = [];
    }
    
    /**
     * 获取历史记录
     */
    getHistory(): ICommand[] {
        return [...this.history];
    }
    
    /**
     * 获取统计信息
     */
    getStats() {
        return {
            ...this.stats,
            pendingCommands: this.getTotalCommandCount(),
            historySize: this.history.length,
            dependencyStats: this.dependencyManager.getStats()
        };
    }
    
    /**
     * 打印统计信息
     */
    printStats(): void {
        const stats = this.getStats();
        
        Log.performance.info('\n=== 命令队列统计信息 ===');
        Log.performance.info(`总命令数: ${stats.totalCommands}`);
        Log.performance.info(`已执行: ${stats.executedCommands}`);
        Log.performance.info(`失败: ${stats.failedCommands}`);
        Log.performance.info(`待执行: ${stats.pendingCommands}`);
        Log.performance.info(`平均执行时间: ${stats.averageExecutionTime.toFixed(2)}ms`);
        Log.performance.info(`历史记录: ${stats.historySize}`);
        Log.performance.info(`依赖排序次数: ${stats.dependencySorts}`);
        
        if (this.enableDependencySort) {
            Log.performance.info('\n--- 依赖统计 ---');
            Log.performance.info(`依赖节点数: ${stats.dependencyStats.totalNodes}`);
            Log.performance.info(`依赖边数: ${stats.dependencyStats.totalEdges}`);
            Log.performance.info(`循环依赖数: ${stats.dependencyStats.circularDependencies}`);
            Log.performance.info(`最大深度: ${stats.dependencyStats.maxDepth}`);
            Log.performance.info(`命令分组数: ${stats.dependencyStats.groups}`);
        }
        
        Log.performance.info('========================\n');
    }
    
    /**
     * 重置统计信息
     */
    resetStats(): void {
        this.stats = {
            totalCommands: 0,
            executedCommands: 0,
            failedCommands: 0,
            averageExecutionTime: 0,
            dependencySorts: 0
        };
    }
    
    // ==================== 依赖管理相关方法 ====================
    
    /**
     * 启用依赖排序
     */
    enableDependencySorting(): void {
        this.enableDependencySort = true;
        Log.ecs.info('✅ 依赖排序已启用');
    }
    
    /**
     * 禁用依赖排序
     */
    disableDependencySorting(): void {
        this.enableDependencySort = false;
        this.dependencyManager.clear();
        Log.ecs.info('依赖排序已禁用');
    }
    
    /**
     * 检测循环依赖
     * @returns 循环依赖的路径列表
     */
    detectCycles(): string[][] {
        return this.dependencyManager.detectCycles();
    }
    
    /**
     * 创建命令分组
     * @param groupName 分组名称
     * @param commandIds 命令 ID 列表
     */
    createCommandGroup(groupName: string, commandIds: string[]): void {
        this.dependencyManager.createGroup(groupName, commandIds);
    }
    
    /**
     * 添加分组依赖
     * @param groupName 分组名称
     * @param dependencyGroupName 依赖的分组名称
     */
    addGroupDependency(groupName: string, dependencyGroupName: string): boolean {
        return this.dependencyManager.addGroupDependency(groupName, dependencyGroupName);
    }
    
    /**
     * 获取命令的所有依赖（递归）
     * @param commandId 命令 ID
     */
    getAllDependencies(commandId: string): string[] {
        return this.dependencyManager.getAllDependencies(commandId);
    }
    
    /**
     * 获取依赖当前命令的所有命令（递归）
     * @param commandId 命令 ID
     */
    getAllDependents(commandId: string): string[] {
        return this.dependencyManager.getAllDependents(commandId);
    }
    
    /**
     * 打印依赖图
     */
    printDependencyGraph(): void {
        this.dependencyManager.printGraph();
    }
    
    /**
     * 可视化依赖图（Mermaid 格式）
     */
    visualizeDependencies(): string {
        return this.dependencyManager.visualize();
    }
}

/**
 * 使用说明：
 * 
 * CommandQueue 现在使用依赖注入，不再是单例。
 * 
 * 通过 DI 容器获取实例：
 * ```typescript
 * import { container, ServiceIdentifiers } from '../../../core/di';
 * const commandQueue = container.resolve<CommandQueue>(ServiceIdentifiers.CommandQueue);
 * ```
 */
